package com.example.supplychainbackend.service.Impl;

import com.example.supplychainbackend.controller.dto.blockchain.UploadInfo;
import com.example.supplychainbackend.controller.dto.project.*;
import com.example.supplychainbackend.controller.dto.project.analysis.NodeExecutionDataDto;
import com.example.supplychainbackend.controller.dto.project.analysis.ProjectAnalysisDto;
import com.example.supplychainbackend.controller.dto.project.analysis.ProjectExecutionDataDto;
import com.example.supplychainbackend.controller.dto.project.analysis.node.NodeChartDto;
import com.example.supplychainbackend.controller.dto.project.analysis.project.ProjectLeadTimeDto;
import com.example.supplychainbackend.controller.dto.user.UserSigDto;
import com.example.supplychainbackend.dao.plan.PlanOrderDao;
import com.example.supplychainbackend.dao.production.ProductionWorkorderDao;
import com.example.supplychainbackend.dao.project.*;
import com.example.supplychainbackend.dao.sales.ContractDao;
import com.example.supplychainbackend.dao.sales.OrderDao;
import com.example.supplychainbackend.entity.plan.PlanOrderEntity;
import com.example.supplychainbackend.entity.plan.ProductionScheduleEntity;
import com.example.supplychainbackend.entity.project.*;
import com.example.supplychainbackend.entity.sales.ContractEntity;
import com.example.supplychainbackend.entity.sales.DeliverableEntity;
import com.example.supplychainbackend.entity.sales.OrderEntity;
import com.example.supplychainbackend.entity.sales.SalesInfoEntity;
import com.example.supplychainbackend.mapper.ProjectMapper;
import com.example.supplychainbackend.service.BlockchainService;
import com.example.supplychainbackend.service.FileService;
import com.example.supplychainbackend.service.ProjectService;
import com.example.supplychainbackend.tool.DateTimeUtils;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;


@Service
@RequiredArgsConstructor
public class ProjectServiceImpl implements ProjectService {
    private final ProjectPlanDao projectPlanDao;
    //private final ProjectProgressDao projectProgressDao;
    private final ProjectDocsDao projectDocsDao;
    private final ProjectFolderDao projectFolderDao;
    private final ProjectFolderFileDao projectFolderFileDao;
    private final ProjectNodeDao projectNodeDao;
    private final OrderDao orderDao;
    private final ContractDao contractDao;
    private final ProjectMapper mapper;

    private final PlanOrderDao planOrderDao;
    private final ProductionWorkorderDao productionWorkorderDao;
    private final FileService fileService;
    private final BlockchainService blockchainService;


    @Override
    public List<ProjectPlanDto> listProjectPlans() {
        return mapper.toProjectPlanDtoList(projectPlanDao.findAll());
    }

    @Override
    public ProjectPlanDto getProjectPlan(String id) {
        //需要组装销售订单信息和交付物列表
        ProjectPlanDto res = mapper.toProjectPlanDto(projectPlanDao.findByProjectPlanNo(id));
        //组装销售订单信息
        SalesInfoDto salesInfo = SalesInfoDto.builder()
                .salesOrderNo(res.getSalesOrderNo())
                .salesOrderName(res.getSalesOrderName())
                .deliveryDate(res.getOrderDeliveryDate())
                .remarks(res.getOrderRemarks())
                .salesperson(res.getSalesPerson())
                .build();
        res.setSalesInfo(salesInfo);
        //组装交付物列表
        String contractNo = res.getContractNo();
        ContractEntity ctEntity = contractDao.findById(contractNo).get();
        List<DeliverableEntity> sdlist = ctEntity.getDeliverable();
        List<DeliverableDto> pdlist = new ArrayList<>();
        for(DeliverableEntity entity :sdlist){
            pdlist.add(DeliverableDto.builder ()
                    .lineNo(entity.getLineNumber())
                    .materialCode(entity.getMaterialNumber())
                    .materialCategory(entity.getMaterialCategory())
                    .materialSubCategory(entity.getMaterialSubCategory())
                    .materialName(entity.getMaterialName())
                    .materialDesc(entity.getMaterialDescription())
                    .deliveryDate(entity.getDeliveryDate())
                    .quantity(entity.getQuantity())
                    .remarks(entity.getRemarks())
                    .build()
            );
        }
        res.setDeliverableList(pdlist);
        return res;
    }

    @Override
    @Transactional
    public String createProjectPlan(String salesOrderNo, UserSigDto sigDto) {
        //生成自增主键  根据销售订单号补充表中信息
        OrderEntity soEntity = orderDao.findById(salesOrderNo).get();
        String ContractNo = soEntity.getContractNumber();
        ContractEntity ctEntity = contractDao.findById(ContractNo).get();
        SalesInfoEntity salesInfoEntity = soEntity.getSalesInfo();

        //生成交付物String
        List<DeliverableEntity> deliverableEntityList = ctEntity.getDeliverable();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < deliverableEntityList.size(); i++) {
            if (i > 0) {
                sb.append(" ");
            }
            sb.append(deliverableEntityList.get(i).getMaterialName());
        }

        ProjectPlanEntity entity = ProjectPlanEntity.builder()
                .contractNo(soEntity.getContractNumber())
                .contractName(ctEntity.getContractName())
                .customerName(ctEntity.getCustomerName())
                .contractRequiredDeliveryDate(ctEntity.getRequiredDeliveryDate())
                .contractSigner(ctEntity.getSignatory())
                .contractSigningUnit(ctEntity.getCompany().toString())
                .contractSalesArea(ctEntity.getSalesArea())
                .contractSigningDate(ctEntity.getSignDate())
                .contractRequirements(ctEntity.getRequirements())
                .contractBusinessDepartment(ctEntity.getBusinessDepartment())
                .salesOrderNo(salesOrderNo)
                .salesOrderName(soEntity.getSalesOrderName())
                .orderType(soEntity.getSalesOrderType())
                .orderDeliveryDate(soEntity.getRequiredDeliveryDate())
                .salesPerson(salesInfoEntity.getSalesman())
                .orderDate(soEntity.getOrderDate())
                //.orderStatus(1)
                .orderRemarks(salesInfoEntity.getRemarks())
                //.orderCreator()
                .orderCreateDate(soEntity.getCreateDate())
                //.orderUpdater()
                .orderUpdateDate(soEntity.getUpdateDate())
                .deliverables(sb.toString())
                //.status(0)  //自动生成了
                .onChain(false)
                .userName(sigDto.getUserName())
                .userId(sigDto.getUserId())
                .enterpriseId(sigDto.getEnterpriseId())
                .enterpriseName(sigDto.getEnterpriseName())
                .build();

        //存项目计划库
        entity = projectPlanDao.save(entity);
        Long id = entity.getId();
        String projectPlanNo = "PP" + DateTimeUtils.getCurrentDateForID() + String.format("%05d",id);
        entity.setProjectPlanNo(projectPlanNo);
        projectPlanDao.save(entity);
        //同时生成项目文档
        ProjectDocsEntity projectDocsEntity = ProjectDocsEntity.builder()
                .projectPlanNo(projectPlanNo)
                .projectPlanStatus(entity.getStatus())
                .contractNo(entity.getContractNo())
                .contractName(entity.getContractName())
                .salesOrderNo(entity.getSalesOrderNo())
                .salesOrderName(entity.getSalesOrderName())
                .customerName(soEntity.getCustomer())
                .documentCount("0")
                .onChain(false)
                .userName(sigDto.getUserName())
                .userId(sigDto.getUserId())
                .enterpriseId(sigDto.getEnterpriseId())
                .enterpriseName(sigDto.getEnterpriseName())
                .build();
        projectDocsDao.save(projectDocsEntity);
        return projectPlanNo;
    }

    @Override
    @Transactional
    public ProjectPlanDto updateProjectPlan(String id, ProjectPlanDto form) {
        ProjectPlanEntity ppEntity = projectPlanDao.findByProjectPlanNo(id);
        mapper.updateProjectPlanEntity(form,ppEntity);

        //由于设置了orphanRemoval = true   不能直接setter
//        res.getPlanDetail().clear();
//        res.getPlanDetail().addAll(mapper.toPlanDetailedEntityList(form.getPlanDetail()));
        //更新项目计划
        ppEntity = projectPlanDao.save(ppEntity);

        //同步更新项目文档
        ProjectDocsEntity pdEntity = projectDocsDao.findByProjectPlanNo(ppEntity.getProjectPlanNo());
        pdEntity.setProjectPlanNo(ppEntity.getProjectPlanNo());
        pdEntity.setProjectPlanStatus(ppEntity.getStatus());
        pdEntity.setContractNo(ppEntity.getContractNo());
        pdEntity.setContractName(ppEntity.getContractName());
        pdEntity.setSalesOrderNo(ppEntity.getSalesOrderNo());
        pdEntity.setCustomerName(ppEntity.getCustomerName());
        pdEntity.setSalesOrderName(ppEntity.getSalesOrderName());
        projectDocsDao.save(pdEntity);

        //判断是否有新的项目计划明细（根据对象的序号是否为空判断） 若有则新增项目节点
        //改成假数据了
//        List<PlanDetailDto> planDetailList = form.getPlanDetail();
//        for(PlanDetailDto pdDto:planDetailList){
//            if(pdDto.getSequenceNo()==null){
//                ProjectNodeEntity nodeEntity = ProjectNodeEntity.builder()
//                        //.title()
//                        //.status()
//                        //.riskLevel() //项目进度中有  但是项目进度中不知道从哪来的
//                        //.responsiblePerson()
//                        //.responsiblePersonStatus()
//                        //.responsibleDepartment()
//                        //.handler(pdDto.getHandler())
//                        //.handlerDepartment()
//                        .plannedStartDate(pdDto.getPlannedStartDate())
//                        .plannedEndDate(pdDto.getPlannedEndDate())
//                        .contractNo(ppEntity.getContractNo())
//                        .contractName(ppEntity.getContractName())
//                        .customerName(ppEntity.getCustomerName())
//                        .requiredDeliveryDate(ppEntity.getContractRequiredDeliveryDate())
//                        .salesOrderNo(ppEntity.getSalesOrderNo())
//                        .salesOrderName(ppEntity.getSalesOrderName())
//                        .deliverables(ppEntity.getDeliverables())
//                        .salesperson(ppEntity.getSalesPerson())
//                        .projectId(ppEntity.getProjectPlanNo())
//                        //.color("绿色")
//                        .build();
//                projectNodeDao.save(nodeEntity);
//            }
//        }

        return mapper.toProjectPlanDto(ppEntity);
    }

//    @Override
//    @Transactional
//    public void deleteProjectPlan(Long id) {
//        projectPlanDao.deleteById(id);
//    }

    //不入库直接查projectplan
    @Override
    public List<ProjectProgressDto> listProjectProgress() {
        List<ProjectPlanEntity> projectPlanList = projectPlanDao.findAll();
        List<ProjectProgressDto> projects = new ArrayList<>();
        for(ProjectPlanEntity entity:projectPlanList){
            projects.add(ProjectProgressDto.builder()
                    .projectPlanNo(entity.getProjectPlanNo())
                    //.riskLevel()
                    //.projectPlanStatus()
                    .contractNo(entity.getContractNo())
                    .contractName(entity.getContractName())
                    .salesOrderInfo(entity.getSalesOrderNo()+"-"+entity.getSalesOrderName())//销售订单编号-销售订单名称
                    .deliverables(entity.getDeliverables())
                    .contractSigner(entity.getContractSigner())
                    .createDate(entity.getCreateDate())
                    .promisedDeliveryDate(entity.getPromisedDeliveryDate())
                    //.requiredDeliveryDate()
                    .forecastDeliveryDate(entity.getForecastDeliveryDate())
                    .build()
            );
        }

        return projects;
    }

    //未使用 看后续情况是否删除
//    @Override
//    public ProjectProgressDto getProjectProgress(Long id) {
//        return mapper.toProjectProgressDto(projectProgressDao.findById(id).get());
//    }
//
//    @Override
//    public Long createProjectProgress(ProjectProgressDto form) {
//        Long id = projectProgressDao.save(mapper.toProjectProgressEntity(form)).getId();
//        return id;
//    }
//
//    @Override
//    public ProjectProgressDto updateProjectProgress(Long id, ProjectProgressDto form) {
//        ProjectProgressEntity newEntity = mapper.toProjectProgressEntity(form);
//        return mapper.toProjectProgressDto(projectProgressDao.save(newEntity));
//    }
//
//    @Override
//    public void deleteProjectProgress(Long id) {
//        projectProgressDao.deleteById(id);
//    }

    //项目文档
    //项目文档的逻辑应该是：在创建项目计划时自动创建关联的项目文档，在编辑项目计划时，同步更新项目文档。
    @Override
    public List<ProjectDocsDto> listProjectDocs() {
        return mapper.toProjectDocsDtoList(projectDocsDao.findAll());
    }

    @Override
    public ProjectDocsDto getProjectDocs(String id) {
        return mapper.toProjectDocsDto(projectDocsDao.findById(Long.valueOf(id)).get());
    }

    @Override
    @Transactional
    public String createProjectDocs(ProjectDocsDto form) {
        ProjectDocsEntity entity = mapper.toProjectDocsEntity(form);
        entity.setOnChain(false);
        return projectDocsDao.save(entity).getProjectId().toString();
    }

    //供内部使用？
    @Override
    @Transactional
    public ProjectDocsDto updateProjectDocs(String id, ProjectDocsDto form) {
        ProjectDocsEntity newEntity = mapper.toProjectDocsEntity(form);
        return mapper.toProjectDocsDto(projectDocsDao.save(newEntity));
    }

    //未使用
//    @Override
//    @Transactional
//    public void deleteProjectDocs(String id) {
//        projectDocsDao.deleteById(Long.valueOf(id));
//    }


    @Override
    @Transactional
    public String createProjectDocsFolder(ProjectFolderDto form) {
        //判断项目文档是否存在
        ProjectDocsEntity res = projectDocsDao.findById(Long.valueOf(form.getProjectId())).get();

        ProjectFolderEntity entity = mapper.toProjectFolderEntity(form);
        entity = projectFolderDao.save(entity);
        if(res.getFolderList()==null){
            res.setFolderList(new ArrayList<>());
        }
        res.getFolderList().add(entity);
        res.setLastModifiedDate(DateTimeUtils.getCurrentDateTime());
        projectDocsDao.save(res);
        return entity.getId().toString();
    }

    @Override
    public List<ProjectFolderFileDto> getProjectDocsFile(String projectId, String folderId) {
        ProjectDocsEntity res = projectDocsDao.findById(Long.valueOf(projectId)).get();
        //遍历项目文件夹列表
        for (ProjectFolderEntity folder : res.getFolderList()) {
            if (folder.getId().toString().equals(folderId)) {
                return mapper.toProjectFolderFileDtoList(folder.getFileList());
            }
        }
        //返回null是否正确呢？ 还是应该抛出异常
        return null;
    }

    @Override
    public void abortProjectDocsFolderFile(String fileId) {
        //直接改fileId的表
        ProjectFolderFileEntity res = projectFolderFileDao.findById(Long.valueOf(fileId)).get();
        res.setStatus(1);
        projectFolderFileDao.save(res);
    }

    @Override
    public Long createProjectNode(ProjectNodeDto form){
        return projectNodeDao.save(mapper.toProjectNodeEntity(form)).getNodeId();
    }
    @Override
    public List<ProjectNodeDto> getProjectNodes() {
        return mapper.toProjectNodeDtoList(projectNodeDao.findAll());
    }

    @Override
    public ProjectAnalysisDto projectAnalysis() {
        ProjectAnalysisDto projectAnalysisDto = new ProjectAnalysisDto();
        ProjectExecutionDataDto projectExecutionDataDto = new ProjectExecutionDataDto();
        ProjectLeadTimeDto projectLeadTimeDto = getProjectLeadTime();
        List<ProjectLeadTimeDto> projectLeadTimeDtos = new ArrayList<>();
        projectLeadTimeDtos.add(projectLeadTimeDto);
        projectExecutionDataDto.setProjectLeadTime(projectLeadTimeDtos);


        projectAnalysisDto.setNodeExecutionData(getNodeExecutionDataDto());
        return projectAnalysisDto;
    }

    ProjectLeadTimeDto getProjectLeadTime(){
        ProjectLeadTimeDto projectLeadTimeDto = new ProjectLeadTimeDto(0f,0f,0f,0f,0f,0f);
        List<ProjectPlanEntity> activeEntities = projectPlanDao.findAllByStatus(2);//进行中项目
        Long SumRequiredLeadTime = 0l;
        Long SumProductionLeadTime = 0l;
        Long SumDeliveryLeadTime = 0l;
        Integer numR = 0;
        Integer numP = 0;
        Integer numD = 0;
        if(activeEntities!=null && !activeEntities.isEmpty()){
            for(int i=0;i<activeEntities.size();i++){
                ProjectPlanEntity curEntity = activeEntities.get(i);
                LocalDate orderDate;
                LocalDate orderCreateDate;
                LocalDate orderDeliveryDate;
                LocalDate endDate;

                String OrderDate = curEntity.getOrderDate();//订单时间
                String OrderCreateDate = curEntity.getOrderCreateDate();//订单创建时间

                try{
                    orderCreateDate = DateTimeUtils.parseDate(OrderCreateDate);
                }catch (Exception e){
                    System.out.println(curEntity.getProjectPlanNo()+"：OrderCreateDate解析失败");
                    continue;
                    //throw new RuntimeException("OrderCreateDate解析失败");
                }
                try{
                    orderDate = DateTimeUtils.parseDate(OrderDate);
                }catch (Exception e){
                    System.out.println(curEntity.getProjectPlanNo()+"：OrderDate解析失败");
                    continue;
                    //throw new RuntimeException("orderDate解析失败");
                }
                //RequiredLeadTime = abs(OrderDate - OrderCreateDate)
                SumRequiredLeadTime += Math.abs(orderDate.toEpochDay()-orderCreateDate.toEpochDay());
                numR++;

                try {
                    String salesOrderNo = curEntity.getSalesOrderNo();
                    PlanOrderEntity planOrderEntity = planOrderDao.findBySalesOrderNo(salesOrderNo);
                    //
                    ProductionScheduleEntity productionScheduleEntity = planOrderEntity.getProductionSchedule();
//                    String planOrderNumber = planOrderEntity.getWorkOrderNumber();
//                    ProductionWorkorderEntity productionWorkorder = productionWorkorderDao.findByPlanOrderNo(planOrderNumber);
                    Integer productionQuantity = productionScheduleEntity.getProductionQuantity();
                    Integer requiredQuantity = productionScheduleEntity.getRequiredQuantity();
                    if(productionQuantity == requiredQuantity)
                    {
                        //生产完成
                        String EndDate = productionScheduleEntity.getActualEndDate();//生产实际完成日期
                        endDate = DateTimeUtils.parseDate(EndDate);
                        //ProductionLeadTime = abs(endDate-OrderCreateDate)
                        SumProductionLeadTime += Math.abs(endDate.toEpochDay()-orderCreateDate.toEpochDay());
                        numP++;
                    }
                    else
                        continue;
                    //
                }catch (Exception e){
                    System.out.println(curEntity.getProjectPlanNo()+"：生产时间获取失败："+e);
                    continue;
                }

                String OrderDeliveryDate = curEntity.getOrderDeliveryDate();//送达时间
                try{
                    orderDeliveryDate = DateTimeUtils.parseDate(OrderDeliveryDate);
                }catch (Exception e){
                    throw new RuntimeException("OrderDelivery解析失败");
                }
                //DeliveryLeadTime = abs(OrderDeliveryDate)
                SumDeliveryLeadTime += Math.abs(orderDeliveryDate.toEpochDay()-orderCreateDate.toEpochDay());
                numD++;
            }
            projectLeadTimeDto.setRequiredLeadTime((float) (SumRequiredLeadTime/numR));
            projectLeadTimeDto.setProductionLeadTime((float)SumProductionLeadTime/numP);
            projectLeadTimeDto.setDeliveryLeadTime((float)SumDeliveryLeadTime/numD);
        }

        activeEntities = projectPlanDao.findAllByStatus(3);//已完成项目
        if(activeEntities!=null && !activeEntities.isEmpty()){
            for(int i=0;i<activeEntities.size();i++){
                ProjectPlanEntity curEntity = activeEntities.get(i);
                LocalDate orderDate;
                LocalDate orderCreateDate;
                LocalDate orderDeliveryDate;
                LocalDate endDate;

                String OrderDate = curEntity.getOrderDate();//订单时间
                String OrderCreateDate = curEntity.getOrderCreateDate();//订单创建时间

                try{
                    orderCreateDate = DateTimeUtils.parseDate(OrderCreateDate);
                }catch (Exception e){
                    System.out.println(curEntity.getProjectPlanNo()+"：OrderCreateDate解析失败");
                    continue;
                    //throw new RuntimeException("OrderCreateDate解析失败");
                }
                try{
                    orderDate = DateTimeUtils.parseDate(OrderDate);
                }catch (Exception e){
                    System.out.println(curEntity.getProjectPlanNo()+"：OrderDate解析失败");
                    continue;
                    //throw new RuntimeException("orderDate解析失败");
                }
                //RequiredLeadTime = abs(OrderDate - OrderCreateDate)
                SumRequiredLeadTime += Math.abs(orderDate.toEpochDay()-orderCreateDate.toEpochDay());
                numR++;

                try {
                    String salesOrderNo = curEntity.getSalesOrderNo();
                    PlanOrderEntity planOrderEntity = planOrderDao.findBySalesOrderNo(salesOrderNo);
                    //
                    ProductionScheduleEntity productionScheduleEntity = planOrderEntity.getProductionSchedule();
//                    String planOrderNumber = planOrderEntity.getWorkOrderNumber();
//                    ProductionWorkorderEntity productionWorkorder = productionWorkorderDao.findByPlanOrderNo(planOrderNumber);
                    Integer productionQuantity = productionScheduleEntity.getProductionQuantity();
                    Integer requiredQuantity = productionScheduleEntity.getRequiredQuantity();
                    if(productionQuantity == requiredQuantity)
                    {
                        //生产完成
                        String EndDate = productionScheduleEntity.getActualEndDate();//生产实际完成日期
                        endDate = DateTimeUtils.parseDate(EndDate);
                        //ProductionLeadTime = abs(endDate-OrderCreateDate)
                        SumProductionLeadTime += Math.abs(endDate.toEpochDay()-orderCreateDate.toEpochDay());
                        numP++;
                    }
                    else
                        continue;
                    //
                }catch (Exception e){
                    System.out.println(curEntity.getProjectPlanNo()+"：生产时间获取失败："+e);
                    continue;
                }

                String OrderDeliveryDate = curEntity.getOrderDeliveryDate();//送达时间
                try{
                    orderDeliveryDate = DateTimeUtils.parseDate(OrderDeliveryDate);
                }catch (Exception e){
                    throw new RuntimeException("OrderDelivery解析失败");
                }
                //DeliveryLeadTime = abs(OrderDeliveryDate)
                SumDeliveryLeadTime += Math.abs(orderDeliveryDate.toEpochDay()-orderCreateDate.toEpochDay());
                numD++;
            }
            projectLeadTimeDto.setHistoricalRequiredLeadTime((float) (SumRequiredLeadTime/numR));
            projectLeadTimeDto.setHistoricalProductionLeadTime((float)SumProductionLeadTime/numP);
            projectLeadTimeDto.setHistoricalDeliveryLeadTime((float)SumDeliveryLeadTime/numD);
        }
        return projectLeadTimeDto;
    }

    NodeExecutionDataDto getNodeExecutionDataDto(){
        NodeExecutionDataDto res = new NodeExecutionDataDto();
        List<String> DeliveryDateRange = new ArrayList<>();
        List<NodeChartDto> nodeExecutionChart = new ArrayList<>();
        List<NodeChartDto> expressNodeExecutionChart = new ArrayList<>();
        List<NodeChartDto> customNodeExecutionChart = new ArrayList<>();
        List<NodeChartDto> largeNodeExecutionChart = new ArrayList<>();
        List<NodeChartDto> aftersalesNodeExecutionChart = new ArrayList<>();

        List<ProjectNodeEntity> projectNodeEntities = projectNodeDao.findAll();
        for(int i =0 ;i<projectNodeEntities.size();i++){
            ProjectNodeEntity curEntity = projectNodeEntities.get(i);
            String projectPlanNo = curEntity.getProjectId();
            ProjectPlanEntity ppEntity = projectPlanDao.findByProjectPlanNo(projectPlanNo);

            //承诺交期
            String promisedDate = ppEntity.getPromisedDeliveryDate();
            //要求交期
            String requiredDate = ppEntity.getContractRequiredDeliveryDate();
            //创建日期
            String createdDate = ppEntity.getOrderCreateDate();

            LocalDate PromisedDate;
            LocalDate RequiredDate;
            LocalDate CreatedDate;
            LocalDate PlanStartDate;
            LocalDate PlanEndDate;

            try{
                CreatedDate = DateTimeUtils.parseDate(createdDate);
            }catch (Exception e){
                System.out.println(curEntity.getNodeId()+"：OrderCreateDate解析失败");
                continue;
            }

            try{
                RequiredDate = DateTimeUtils.parseDate(requiredDate);
            }catch (Exception e){
                System.out.println(curEntity.getNodeId()+"：ContractRequiredDeliveryDate解析失败");
                continue;
            }

            try{
                PromisedDate = DateTimeUtils.parseDate(promisedDate);
            }catch (Exception e){
                System.out.println(curEntity.getNodeId()+"：PromisedDeliveryDate解析失败");
                continue;
            }

            try{
                PlanStartDate = DateTimeUtils.parseDate(curEntity.getPlannedStartDate());
                PlanEndDate = DateTimeUtils.parseDate(curEntity.getPlannedEndDate());
            }catch (Exception e) {
                System.out.println(curEntity.getNodeId()+"：PlannedStart/EndDate解析失败");
                continue;
            }

            //搞搞DeliveryDateRange
            if(DeliveryDateRange.isEmpty()){
                DeliveryDateRange.add(promisedDate);
                DeliveryDateRange.add(promisedDate);
            }else{
                LocalDate firstDate = DateTimeUtils.parseDate(DeliveryDateRange.get(0));
                LocalDate lastDate = DateTimeUtils.parseDate(DeliveryDateRange.get(1));
                if(firstDate.toEpochDay()>PromisedDate.toEpochDay())
                    DeliveryDateRange.set(0,promisedDate);
                else if(lastDate.toEpochDay()<PromisedDate.toEpochDay())
                    DeliveryDateRange.set(1,promisedDate);
            }

            NodeChartDto curNode = new NodeChartDto(curEntity.getNodeId().toString(),Math.abs(PlanEndDate.toEpochDay()-PlanStartDate.toEpochDay()),Math.abs(RequiredDate.toEpochDay()-CreatedDate.toEpochDay()));
            nodeExecutionChart.add(curNode);
            switch(curEntity.getTitle()){
                case "express":
                    expressNodeExecutionChart.add(curNode);
                    break;
                case "custom":
                    customNodeExecutionChart.add(curNode);
                    break;
                case "large":
                    largeNodeExecutionChart.add(curNode);
                    break;
                case "aftersales":
                    aftersalesNodeExecutionChart.add(curNode);
                    break;
            }
        }

        res.setNodeExecutionChart(nodeExecutionChart);
        res.setDeliveryDateRange(DeliveryDateRange);
        res.setExpressNodeExecutionChart(expressNodeExecutionChart);
        res.setCustomNodeExecutionChart(customNodeExecutionChart);
        res.setLargeNodeExecutionChart(largeNodeExecutionChart);
        res.setAftersalesNodeExecutionChart(aftersalesNodeExecutionChart);
        return res;
    }


    @Override
    public List<ProjectPlanDto> test(Integer status) {
        return mapper.toProjectPlanDtoList(projectPlanDao.findAllByStatus(status));
    }

    //文件上传逻辑 调用fileService中的方法，将数据存到项目文档文件数据库中
    //理论上 同一个文件夹下不能有同名文件
    @Override
    public String uploadProjectDocsFile(MultipartFile file, String folderId) throws IOException {
        ProjectFolderEntity projectFolderEntity = projectFolderDao.findById(Long.valueOf(folderId)).get();
        List<ProjectFolderFileEntity> projectFolderFileEntityList = projectFolderEntity.getFileList();
        //判断当前文件夹下是否有同名文件 如果列表中有一个文件的文件名与当前文件名相同，则抛出异常
        for(ProjectFolderFileEntity projectFolderFileEntity:projectFolderFileEntityList){
            if(projectFolderFileEntity.getFileName().equals(file.getOriginalFilename())){
                throw new IOException("文件名已存在");
            }
        }
        String url = fileService.storeFile(file);
        ProjectFolderFileEntity projectFolderFileEntity = ProjectFolderFileEntity.builder()
                .fileName(file.getOriginalFilename())
                .fileSize(String.valueOf(file.getSize()))
                .url(url)
                .build();

        projectFolderEntity.getFileList().add(projectFolderFileEntity);
        projectFolderDao.save(projectFolderEntity);
        return url;
    }

    @Override
    public UploadInfo uploadToChainPlan(String id) {
        ProjectPlanDto plan = this.getProjectPlan(id);
        if (null!=plan){
            UploadInfo txInfo = blockchainService.uploadProjectPlan(id, plan.toString());
            plan.setOnChain(true);
            plan.setCommitTime(txInfo.getCommitTime());
            plan.setTransactionId(txInfo.getTransactionId());
            projectPlanDao.save(mapper.toProjectPlanEntity(plan));
            return txInfo;
        }
        throw new RuntimeException("plan not found");
    }

    @Override
    public UploadInfo uploadToChainDocs(String id) {
        ProjectDocsDto docs = this.getProjectDocs(id);
        if (null!=docs){
            UploadInfo txInfo = blockchainService.uploadProjectDoc(id, docs.toString());
            docs.setOnChain(true);
            docs.setCommitTime(txInfo.getCommitTime());
            docs.setTransactionId(txInfo.getTransactionId());
            projectDocsDao.save(mapper.toProjectDocsEntity(docs));
            return txInfo;
        }
        throw new RuntimeException("docs not found");
    }

    @Override
    public List<ProjectPlanDto> listProjectPlansByEid(String eid) {
        return mapper.toProjectPlanDtoList(projectPlanDao.findAllByEnterpriseId(eid));
    }

    @Override
    public List<ProjectDocsDto> listProjectDocsByEid(String eid) {
        return mapper.toProjectDocsDtoList(projectDocsDao.findAllByEnterpriseId(eid));
    }
}
